==========================================================================

  ansic.y: PCYACC grammar description for ANSI C
  version 1.0
  grammar by Xing Liu; error processing by Jeff Taylor

  PCYACC (R) ABRAXAS SOFTWARE, ALL RIGHT RESERVED.

  Reference: The C Programming Language (Reference Manual)
             Second Edition
             By B.W. Kernighan and D.M. Ritchie

===========================================================================
*/

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "global.h"
#include "errorlib.h"
#include "nodes\allnodes.h"
extern translation_unit* translationUnit;
extern char tokval[BUFSIZE];
%}

%union {
  int   i;
  float r;
  char *s;
  Node* node;
  List* list;
}

/*----------------------- special symbols -------------------------------*/

%token DDD		/* three dots ... */

/*--------------------------- constants ---------------------------------*/

%token	CHARACTER_CONSTANT FLOAT_CONSTANT INTEGER_CONSTANT STRING

/*--------------------------- identifiers -------------------------------*/

%token	IDENTIFIER TYPENAME ENUMERATION_CONSTANT

/*--------------------------- key words ---------------------------------*/

%token	Auto		Break		Case		Char		Const
%token	Continue	Default		Do  	 	Double		Else
%token	Enum		Extern 		Float		For		Goto
%token	If		Int  	  	Long	 	Register	Return
%token	Short		Signed 		Sizeof	 	Static		Struct
%token	Switch		Typedef		Void 	  	Volatile	Union
%token	Unsigned	While

/*--------------------------- combined operators ------------------------*/

/* binary logicals and comparators */

%token	OROR	ANDAND	EQU	NEQ	LEQ	GEQ

/* shift operators */						

%token	SHL	SHR

/* unary increments */

%token	ADDADD	SUBSUB

/* pointer */

%token	PTR

/* assignments */

%token	ADDEQ	SUBEQ	MULEQ	DIVEQ	MODEQ
%token	SHLEQ	SHREQ	ANDEQ	XOREQ	IOREQ

/*--------------------------- operator precedence -----------------------*/

/* comma operator */

%left	comma

/* assignment operators */

%right	ADDEQ	SUBEQ	MULEQ	DIVEQ	MODEQ
	SHLEQ	SHREQ	BANDEQ	BXOREQ	BOREQ

/* binary operators */

%right	'?'	':'
%left	OROR
%left	ANDAND
%left	BOR
%left	BEOR
%left	BAND
%left	EQU
%left	NEQ
%left	LEQ	GEQ
%left	SHL	SHR
%left	ADD	SUB
%left	MUL	DIV	MOD

/* unary operators */

%right	ADDADD	SUBSUB	'~'	'!'
	UNIADD	UNISUB	UNIMUL	UNIBAND
	Sizeof	'*'

/* special operators */

%left	'('	'['	'.'	PTR

/*--------------------------- start symbol ------------------------------*/

%start translation_unit

%%

translation_unit 
  : external_declaration 
    { 
      translationUnit->addNodeLast($1.node);
    }                             
  | translation_unit external_declaration
    { 
      translationUnit->addNodeLast($2.node);
    }
  | error			/* last ditch error recovery */
  ;

external_declaration
  : function_definition
    {
      external_declaration* externalDeclaration;
      externalDeclaration = new external_declaration;
      externalDeclaration->setNodeType(EXTERNAL_DECLARATION);
      externalDeclaration->setDecompositionRule(1);
      externalDeclaration->functionDefinition = $1.node;
      $$.node = externalDeclaration;
    }
  | declaration
    {
      external_declaration* externalDeclaration;
      externalDeclaration = new external_declaration;
      externalDeclaration->setNodeType(EXTERNAL_DECLARATION);
      externalDeclaration->setDecompositionRule(2);
      externalDeclaration->Declaration = $1.node;
      $$.node = externalDeclaration;
    }
  ;

function_definition
  : declaration_specifiers declarator declaration_list compound_statement
    {
      function_definition* functionDefinition;
      functionDefinition = new function_definition;
      functionDefinition->setNodeType(FUNCTION_DEFINITION);
      functionDefinition->setDecompositionRule(1);
	  functionDefinition->declarationSpecifiers = $1.list;
	  functionDefinition->Declarator = $2.node;
	  functionDefinition->declarationList = $3.list;
	  functionDefinition->compoundStatement = $4.node;
      $$.node = functionDefinition;
    }
  | declaration_specifiers declarator                  compound_statement
    {
      function_definition* functionDefinition;
      functionDefinition = new function_definition;
      functionDefinition->setNodeType(FUNCTION_DEFINITION);
      functionDefinition->setDecompositionRule(2);
	  functionDefinition->declarationSpecifiers = $1.list;
	  functionDefinition->Declarator = $2.node;
	  functionDefinition->declarationList = NULL;
	  functionDefinition->compoundStatement = $3.node;
      $$.node = functionDefinition;
    }
  |                        declarator declaration_list compound_statement
    {
      function_definition* functionDefinition;
      functionDefinition = new function_definition;
      functionDefinition->setNodeType(FUNCTION_DEFINITION);
      functionDefinition->setDecompositionRule(3);
	  functionDefinition->declarationSpecifiers = NULL;
	  functionDefinition->Declarator = $1.node;
	  functionDefinition->declarationList = $2.list;
	  functionDefinition->compoundStatement = $3.node;
      $$.node = functionDefinition;
    }
  |                        declarator                  compound_statement
    {
      function_definition* functionDefinition;
      functionDefinition = new function_definition;
      functionDefinition->setNodeType(FUNCTION_DEFINITION);
      functionDefinition->setDecompositionRule(4);
	    functionDefinition->declarationSpecifiers = NULL;
	    functionDefinition->Declarator = $1.node;
	    functionDefinition->declarationList = NULL;
	     functionDefinition->compoundStatement = $2.node;
      $$.node = functionDefinition;
    }
	/* insert wrong or missing parts of function headers */
  | declaration_specifiers error		       compound_statement
  |                        declarator error            compound_statement
  ;

declaration
  : declaration_specifiers init_declarator_list semicolon
    {
      declaration* Declaration;
      Declaration = new declaration;
      Declaration->setNodeType(DECLARATION);
      Declaration->setDecompositionRule(1);
	    Declaration->declarationSpecifiers = $1.list;
	    Declaration->initDeclaratorList = $2.list;
      Declaration->Semicolon = $3.node;
      //john(Declaration)
      $$.node = Declaration;
    }
  | declaration_specifiers                      semicolon
    {
      declaration* Declaration;
      Declaration = new declaration;
      Declaration->setNodeType(DECLARATION);
      Declaration->setDecompositionRule(2);
      Declaration->declarationSpecifiers = $1.list;
      Declaration->Semicolon = $2.node;
      $$.node = Declaration;
    }
	/* fixup incorrect initializers list */
  | declaration_specifiers error		semicolon	{ yyerrok; }
  ;

declaration_list
  : declaration
    {
	  declaration_list* declarationList;
	  declarationList = new declaration_list;
	  declarationList->setNodeType(DECLARATION_LIST);
    declarationList->setNewlineSeparated();
	  declarationList->addNodeLast($1.node);
	  $$.list = declarationList;
    }
  | declaration_list declaration
    {
	  $1.list->addNodeLast($2.node);
	  $$.list = $1.list;
    }
  ;

declaration_specifiers
  : declaration_specifier
    {
	    declaration_specifiers* declarationSpecifiers;
	    declarationSpecifiers = new declaration_specifiers;
	    declarationSpecifiers->setNodeType(DECLARATION_SPECIFIERS);
	    declarationSpecifiers->addNodeLast($1.node);
	    $$.list = declarationSpecifiers;
    }
  | declaration_specifiers declaration_specifier
    {
	    $1.list->addNodeLast($2.node);
	    $$.list = $1.list;
    }
  ;

declaration_specifier
  : storage_class_specifier
    {
	  declaration_specifier* declarationSpecifier;
	  declarationSpecifier = new declaration_specifier;
	  declarationSpecifier->setNodeType(DECLARATION_SPECIFIER);
	  declarationSpecifier->setDecompositionRule(1);
    declarationSpecifier->storageClassSpecifier = $1.node;
	  $$.node = declarationSpecifier;
	}
  | type_specifier
    {
	  declaration_specifier* declarationSpecifier;
	  declarationSpecifier = new declaration_specifier;
	  declarationSpecifier->setNodeType(DECLARATION_SPECIFIER);
	  declarationSpecifier->setDecompositionRule(2);
    declarationSpecifier->typeSpecifier = $1.node;
	  $$.node = declarationSpecifier;
	}
  | type_qualifier
    {
	  declaration_specifier* declarationSpecifier;
	  declarationSpecifier = new declaration_specifier;
	  declarationSpecifier->setNodeType(DECLARATION_SPECIFIER);
	  declarationSpecifier->setDecompositionRule(3);
    declarationSpecifier->typeQualifier = $1.node;
	  $$.node = declarationSpecifier;
	}
  ;

storage_class_specifier
  : keyword_Auto
    {
      storage_class_specifier* storageClassSpecifier;
      storageClassSpecifier = new storage_class_specifier;
      storageClassSpecifier->setNodeType(STORAGE_CLASS_SPECIFIER);
      storageClassSpecifier->setDecompositionRule(1);
      storageClassSpecifier->Keyword = $1.node;
      $$.node = storageClassSpecifier;
    }
  | keyword_Extern
    {
      storage_class_specifier* storageClassSpecifier;
      storageClassSpecifier = new storage_class_specifier;
      storageClassSpecifier->setNodeType(STORAGE_CLASS_SPECIFIER);
      storageClassSpecifier->setDecompositionRule(2);
      storageClassSpecifier->Keyword = $1.node;
      $$.node = storageClassSpecifier;
    }
  | keyword_Register
    {
      storage_class_specifier* storageClassSpecifier;
      storageClassSpecifier = new storage_class_specifier;
      storageClassSpecifier->setNodeType(STORAGE_CLASS_SPECIFIER);
      storageClassSpecifier->setDecompositionRule(3);
      storageClassSpecifier->Keyword = $1.node;
      $$.node = storageClassSpecifier;
    }
  | keyword_Static
    {
      storage_class_specifier* storageClassSpecifier;
      storageClassSpecifier = new storage_class_specifier;
      storageClassSpecifier->setNodeType(STORAGE_CLASS_SPECIFIER);
      storageClassSpecifier->setDecompositionRule(4);
      storageClassSpecifier->Keyword = $1.node;
      $$.node = storageClassSpecifier;
    }
  | keyword_Typedef		/* need to insert type names into symbols table */
    {
      storage_class_specifier* storageClassSpecifier;
      storageClassSpecifier = new storage_class_specifier;
      storageClassSpecifier->setNodeType(STORAGE_CLASS_SPECIFIER);
      storageClassSpecifier->setDecompositionRule(5);
      storageClassSpecifier->Keyword = $1.node;
      $$.node = storageClassSpecifier;
    }
  ;

type_specifier
  : keyword_Char
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(1);
      typeSpecifier->Keyword = $1.node;
      $$.node = typeSpecifier;
    }
  | keyword_Double
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(2);
      typeSpecifier->Keyword = $1.node;
      $$.node = typeSpecifier;
    }
  | keyword_Float
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(3);
      typeSpecifier->Keyword = $1.node;
      $$.node = typeSpecifier;
    }
  | keyword_Int
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(4);
      typeSpecifier->Keyword = $1.node;
      $$.node = typeSpecifier;
    }
  | keyword_Long
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(5);
      typeSpecifier->Keyword = $1.node;
      $$.node = typeSpecifier;
    }
  | keyword_Short
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(6);
      typeSpecifier->Keyword = $1.node;
      $$.node = typeSpecifier;
    }
  | keyword_Signed
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(7);
      typeSpecifier->Keyword = $1.node;
      $$.node = typeSpecifier;
    }
  | keyword_Unsigned
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(8);
      typeSpecifier->Keyword = $1.node;
      $$.node = typeSpecifier;
    }
  | keyword_Void
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(9);
      typeSpecifier->Keyword = $1.node;
      $$.node = typeSpecifier;
    }
  |   TYPENAME
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(10);
      type* Type;
      Type = new type(strlen($1.s));
      Type->setNodeType(TYPE);
      strcpy(Type->stringRepresentation, $1.s);
      Type->storeIgnored();
      typeSpecifier->Type = Type;
      $$.node = typeSpecifier;
    }
  | aggregate_specifier
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(11);
      typeSpecifier->aggregateSpecifier = $1.node;
      $$.node = typeSpecifier;
    }
  |   identifier_name
    {
      type_specifier* typeSpecifier;
      typeSpecifier = new type_specifier;
      typeSpecifier->setNodeType(TYPE_SPECIFIER);
      typeSpecifier->setDecompositionRule(11);
      typeSpecifier->Identifier = $1.node;
      $$.node = typeSpecifier;
    }
  ;

type_qualifier
  : keyword_Const
    {
      type_qualifier* typeQualifier;
      typeQualifier = new type_qualifier;
      typeQualifier->setNodeType(TYPE_QUALIFIER);
      typeQualifier->setDecompositionRule(1);
      typeQualifier->Keyword = $1.node;
      $$.node = typeQualifier;
    }
  | keyword_Volatile
    {
      type_qualifier* typeQualifier;
      typeQualifier = new type_qualifier;
      typeQualifier->setNodeType(TYPE_QUALIFIER);
      typeQualifier->setDecompositionRule(2);
      typeQualifier->Keyword = $1.node;
      $$.node = typeQualifier;
    }
  ;

aggregate_specifier
  : aggregate_type identifier_name open_c_br aggregate_member_list close_c_br
    {
      aggregate_specifier* aggregateSpecifier;
      aggregateSpecifier = new aggregate_specifier;
      aggregateSpecifier->setNodeType(AGGREGATE_SPECIFIER);
      aggregateSpecifier->setDecompositionRule(1);
      aggregateSpecifier->aggregateType = $1.node;
      aggregateSpecifier->Identifier = $2.node;
      aggregateSpecifier->openCBr = $3.node;
      aggregateSpecifier->aggregateMemberList = $4.node;
      aggregateSpecifier->closeCBr = $5.node;
      $$.node = aggregateSpecifier;
    }
  | aggregate_type            open_c_br aggregate_member_list close_c_br
    {
      aggregate_specifier* aggregateSpecifier;
      aggregateSpecifier = new aggregate_specifier;
      aggregateSpecifier->setNodeType(AGGREGATE_SPECIFIER);
      aggregateSpecifier->setDecompositionRule(2);
      aggregateSpecifier->aggregateType = $1.node;
      aggregateSpecifier->openCBr = $2.node;
      aggregateSpecifier->aggregateMemberList = $3.node;
      aggregateSpecifier->closeCBr = $4.node;
      $$.node = aggregateSpecifier;
    }
  | aggregate_type identifier_name
    {
      aggregate_specifier* aggregateSpecifier;
      aggregateSpecifier = new aggregate_specifier;
      aggregateSpecifier->setNodeType(AGGREGATE_SPECIFIER);
      aggregateSpecifier->setDecompositionRule(3);
      aggregateSpecifier->aggregateType = $1.node;
      aggregateSpecifier->Identifier = $2.node;
      $$.node = aggregateSpecifier;
    }
  ;

aggregate_type
  : keyword_Enum
    {
      aggregate_type* aggregateType;
      aggregateType = new aggregate_type;
      aggregateType->setNodeType(AGGREGATE_TYPE);
      aggregateType->setDecompositionRule(1);
      aggregateType->Keyword = $1.node;
      $$.node = aggregateType;
    }
  | keyword_Struct
    {
      aggregate_type* aggregateType;
      aggregateType = new aggregate_type;
      aggregateType->setNodeType(AGGREGATE_TYPE);
      aggregateType->setDecompositionRule(2);
      aggregateType->Keyword = $1.node;
      $$.node = aggregateType;
    }
  | keyword_Union
    {
      aggregate_type* aggregateType;
      aggregateType = new aggregate_type;
      aggregateType->setNodeType(AGGREGATE_TYPE);
      aggregateType->setDecompositionRule(3);
      aggregateType->Keyword = $1.node;
      $$.node = aggregateType;
    }
  ;

aggregate_member_list
  : struct_declaration_list
    {
      aggregate_member_list* aggregateMemberList;
      aggregateMemberList = new aggregate_member_list;
      aggregateMemberList->setNodeType(AGGREGATE_MEMBER_LIST);
      aggregateMemberList->setDecompositionRule(1);
      aggregateMemberList->structDeclarationList = $1.list;
      $$.node = aggregateMemberList;
    }
  | enumerator_list
    {
      aggregate_member_list* aggregateMemberList;
      aggregateMemberList = new aggregate_member_list;
      aggregateMemberList->setNodeType(AGGREGATE_MEMBER_LIST);
      aggregateMemberList->setDecompositionRule(2);
      aggregateMemberList->enumeratorList = $1.list;
      $$.node = aggregateMemberList;
    }
  ;

struct_declaration_list
  : struct_declaration
    {
      struct_declaration_list* structDeclarationList;
      structDeclarationList = new struct_declaration_list;
      structDeclarationList->setNodeType(STRUCT_DECLARATION_LIST);
      structDeclarationList->addNodeLast($1.node);
      $$.node = structDeclarationList;
    }
  | struct_declaration_list struct_declaration
    {
      $1.list->addNodeLast($2.node);
      $$.list = $1.list;
    }
  ;

init_declarator_list
  : init_declarator
    { 
	  init_declarator_list* initDeclaratorList;
	  initDeclaratorList = new init_declarator_list;
	  initDeclaratorList->setNodeType(INIT_DECLARATOR_LIST);
	  initDeclaratorList->addNodeLast($1.node);
    initDeclaratorList->setCommaSeparated();
	  $$.list = initDeclaratorList;
	}
  | init_declarator_list op_comma init_declarator
    {
 	  $1.list->addNodeLast($2.node);
 	  $1.list->addNodeLast($3.node);
	  $$.list = $1.list;
	}
  ;

init_declarator
  : declarator
    {
	  init_declarator* initDeclarator;
	  initDeclarator = new init_declarator;
	  initDeclarator->setNodeType(INIT_DECLARATOR);
	  initDeclarator->setDecompositionRule(1);
	  initDeclarator->Declarator = $1.node;
	  $$.node = initDeclarator;
	}
  | declarator equals initializer
    {
	  init_declarator* initDeclarator;
	  initDeclarator = new init_declarator;
	  initDeclarator->setNodeType(INIT_DECLARATOR);
	  initDeclarator->setDecompositionRule(2);
 	  initDeclarator->Declarator = $1.node;
    initDeclarator->Equals = $2.node;
  	initDeclarator->Initializer = $3.node;
	  $$.node = initDeclarator;
	}
  ;

struct_declaration
  : declaration_specifiers struct_declarator_list semicolon
    {
      struct_declaration* structDeclaration;
      structDeclaration = new struct_declaration;
      structDeclaration->setNodeType(STRUCT_DECLARATION);
      structDeclaration->setDecompositionRule(1); // =)
      structDeclaration->declarationSpecifiers = $1.list;
      structDeclaration->structDeclaratorList = $2.list;
      structDeclaration->Semicolon = $3.node;
      $$.node = structDeclaration;
    }
  | error semicolon		{ yyerrok; }	/* fixup incorrect structures */
  ;

struct_declarator_list
  : struct_declarator
    {
      struct_declarator_list* structDeclaratorList;
      structDeclaratorList = new struct_declarator_list;
      structDeclaratorList->setNodeType(STRUCT_DECLARATOR_LIST);
      structDeclaratorList->setCommaSeparated();
      structDeclaratorList->addNodeLast($1.node);
      $$.list = structDeclaratorList;
    }
  | struct_declarator_list op_comma struct_declarator
    {
      $1.list->addNodeLast($2.node);
      $1.list->addNodeLast($3.node);
      $$.list = $1.list;
    }
  ;

struct_declarator
  : declarator
    {
      struct_declarator* structDeclarator;
      structDeclarator = new struct_declarator;
      structDeclarator->setNodeType(STRUCT_DECLARATOR);
      structDeclarator->setDecompositionRule(1);
      structDeclarator->Declarator = $1.node;
      $$.node = structDeclarator;
    }
  | declarator colon constant_expression
    {
      struct_declarator* structDeclarator;
      structDeclarator = new struct_declarator;
      structDeclarator->setNodeType(STRUCT_DECLARATOR);
      structDeclarator->setDecompositionRule(2);
      structDeclarator->Declarator = $1.node;
      structDeclarator->Colon = $2.node;
      structDeclarator->constantExpression = $3.node;
      $$.node = structDeclarator;
    }
  |            colon constant_expression
    {
      struct_declarator* structDeclarator;
      structDeclarator = new struct_declarator;
      structDeclarator->setNodeType(STRUCT_DECLARATOR);
      structDeclarator->setDecompositionRule(3);
      structDeclarator->Colon = $1.node;
      structDeclarator->constantExpression = $2.node;
      $$.node = structDeclarator;
    }
  ;

enumerator_list
  : enumerator
    {
      enumerator_list* enumeratorList;
      enumeratorList = new enumerator_list;
      enumeratorList->setNodeType(ENUMERATOR_LIST);
      enumeratorList->setCommaSeparated();
      enumeratorList->addNodeLast($1.node);
      $$.list = enumeratorList;
    }
  | enumerator_list op_comma enumerator
    {
      $1.list->addNodeLast($2.list);
      $1.list->addNodeLast($3.list);
      $$.list = $1.list;
    }
  ;

enumerator		/* need to insert enumeration names into symbol table */
  : identifier_name
    {
      enumerator* keyword_Enumerator;
      keyword_Enumerator = new enumerator;
      keyword_Enumerator->setNodeType(ENUMERATOR);
      keyword_Enumerator->setDecompositionRule(1);
      keyword_Enumerator->Identifier = $1.node;
      $$.node = keyword_Enumerator;
    }
  | identifier_name equals constant_expression
    {
      enumerator* keyword_Enumerator;
      keyword_Enumerator = new enumerator;
      keyword_Enumerator->setNodeType(ENUMERATOR);
      keyword_Enumerator->setDecompositionRule(2);
      keyword_Enumerator->Identifier = $1.node;
      keyword_Enumerator->Equals = $2.node;
      keyword_Enumerator->constantExpression = $3.node;
      $$.node = keyword_Enumerator;
    }
  | error		/* fixup incorrect enumeration tags */
  ;

declarator
  : pointer direct_declarator
    {
	    declarator* Declarator;
	    Declarator = new declarator;
	    Declarator->setNodeType(DECLARATOR);
	    Declarator->setDecompositionRule(1); 
	    Declarator->Pointer = $1.node;
	    Declarator->directDeclarator = $2.node;
	    $$.node = Declarator;
	  }
  |         direct_declarator
    {
	    declarator* Declarator;
	    Declarator = new declarator;
	    Declarator->setNodeType(DECLARATOR);
	    Declarator->setDecompositionRule(2); 
	    Declarator->directDeclarator = $1.node;
	    $$.node = Declarator;
    }
  ;

direct_declarator
  : identifier_name
    {
	  direct_declarator* directDeclarator;
	  directDeclarator = new direct_declarator;
	  directDeclarator->setNodeType(DIRECT_DECLARATOR);
	  directDeclarator->setDecompositionRule(1);

	  directDeclarator->Identifier = $1.node;
	  $$.node = directDeclarator;
	}
  | open_r_br declarator close_r_br 
    {
	  direct_declarator* directDeclarator;
	  directDeclarator = new direct_declarator;
	  directDeclarator->setNodeType(DIRECT_DECLARATOR);
	  directDeclarator->setDecompositionRule(2);
	  directDeclarator->openRBr = $1.node;
	  directDeclarator->Declarator = $2.node;
	  directDeclarator->closeRBr = $3.node;
	  $$.node = directDeclarator;
	 }
  | direct_declarator open_s_br constant_expression close_s_br
    {
	  direct_declarator* directDeclarator;
	  directDeclarator = new direct_declarator;
	  directDeclarator->setNodeType(DIRECT_DECLARATOR);
	  directDeclarator->setDecompositionRule(3);
	  directDeclarator->directDeclarator = $1.node;
	  directDeclarator->openSBr = $2.node;
	  directDeclarator->constantExpression = $3.node;
	  directDeclarator->closeSBr = $4.node;
	  $$.node = directDeclarator;
    }
  | direct_declarator open_s_br                     close_s_br
    {
	  direct_declarator* directDeclarator;
	  directDeclarator = new direct_declarator;
	  directDeclarator->setNodeType(DIRECT_DECLARATOR);
	  directDeclarator->setDecompositionRule(4);
	  directDeclarator->directDeclarator = $1.node;
	  directDeclarator->openSBr = $2.node;
	  directDeclarator->closeSBr = $3.node;
	  $$.node = directDeclarator;
	}
  | direct_declarator open_r_br parameter_type_list close_r_br
    {
	  direct_declarator* directDeclarator;
	  directDeclarator = new direct_declarator;
	  directDeclarator->setNodeType(DIRECT_DECLARATOR);
	  directDeclarator->setDecompositionRule(5);
	  directDeclarator->directDeclarator = $1.node;
	  directDeclarator->openRBr = $2.node;
	  directDeclarator->parameterTypeList = $3.node;
	  directDeclarator->closeRBr = $4.node;
	  $$.node = directDeclarator;
	}
  | direct_declarator open_r_br identifier_list     close_r_br
    {
	  direct_declarator* directDeclarator;
	  directDeclarator = new direct_declarator;
	  directDeclarator->setNodeType(DIRECT_DECLARATOR);
	  directDeclarator->setDecompositionRule(6);
	  directDeclarator->directDeclarator = $1.node;
	  directDeclarator->openRBr = $2.node;
	  directDeclarator->identifierList = $3.list;
	  directDeclarator->closeRBr = $4.node;
	  $$.node = directDeclarator;
	}
  | direct_declarator open_r_br                     close_r_br
    {
	  direct_declarator* directDeclarator;
	  directDeclarator = new direct_declarator;
	  directDeclarator->setNodeType(DIRECT_DECLARATOR);
	  directDeclarator->setDecompositionRule(7);
	  directDeclarator->directDeclarator = $1.node;
	  directDeclarator->openRBr = $2.node;
	  directDeclarator->closeRBr = $3.node;
	  $$.node = directDeclarator;
	}
  ;

pointer
  : asterisk type_qualifier_list
    {
	  pointer* Pointer;
	  Pointer = new pointer;
	  Pointer->setNodeType(POINTER);
	  Pointer->setDecompositionRule(1);
	  Pointer->Asterisk = $1.list;
	  Pointer->typeQualifierList = $2.list;
	  $$.node = Pointer;
	}
  | asterisk
    {
	  pointer* Pointer;
	  Pointer = new pointer;
	  Pointer->setNodeType(POINTER);
	  Pointer->setDecompositionRule(2);
	  Pointer->Asterisk = $1.list;
	  $$.node = Pointer;
	}
  | asterisk type_qualifier_list pointer
    {
	  pointer* Pointer;
	  Pointer = new pointer;
	  Pointer->setNodeType(POINTER);
	  Pointer->setDecompositionRule(3);
	  Pointer->Asterisk = $1.list;
	  Pointer->typeQualifierList = $2.list;
	  Pointer->Pointer = $3.node;
	  $$.node = Pointer;
	}
  | asterisk                     pointer
    {
	  pointer* Pointer;
	  Pointer = new pointer;
	  Pointer->setNodeType(POINTER);
	  Pointer->setDecompositionRule(4);
	  Pointer->Asterisk = $1.list;
	  Pointer->Pointer = $2.node;
	  $$.node = Pointer;
	}
  ;

type_qualifier_list
  : type_qualifier
    {
	  type_qualifier_list* typeQualifierList;
	  typeQualifierList = new type_qualifier_list;
	  typeQualifierList->setNodeType(TYPE_QUALIFIER_LIST);
	  typeQualifierList->addNodeLast($1.node);
	  $$.node = typeQualifierList;
	}
  | type_qualifier_list type_qualifier
    {
	  $1.list->addNodeLast($2.node);
	  $$.list = $1.list;
	}
  ;

parameter_type_list
  : parameter_list
    {
	  parameter_type_list* parameterTypeList;
	  parameterTypeList = new parameter_type_list;
	  parameterTypeList->setNodeType(PARAMETER_TYPE_LIST);
	  parameterTypeList->setDecompositionRule(1);
	  parameterTypeList->parameterList = $1.list;
	  $$.node = parameterTypeList;
	}
  | parameter_list op_comma dots
    {
	  parameter_type_list* parameterTypeList;
	  parameterTypeList = new parameter_type_list;
	  parameterTypeList->setNodeType(PARAMETER_TYPE_LIST);
	  parameterTypeList->setDecompositionRule(2);
	  parameterTypeList->parameterList = $1.list;
	  parameterTypeList->Comma = $2.list;
	  parameterTypeList->Dots = $3.list;
	  $$.node = parameterTypeList;
	}
  ;

parameter_list
  : parameter_declaration
    {
	  parameter_list* parameterList;
	  parameterList = new parameter_list;
	  parameterList->setNodeType(PARAMETER_LIST);
    parameterList->setCommaSeparated();
	  parameterList->addNodeLast($1.node);
	  $$.list = parameterList;
	}
  | parameter_list op_comma parameter_declaration
    {
	  $1.list->addNodeLast($2.node);
	  $1.list->addNodeLast($3.node);
	  $$.list = $1.list;
	}
  ;

parameter_declaration
  : declaration_specifiers declarator
    {
	  parameter_declaration* parameterDeclaration;
	  parameterDeclaration = new parameter_declaration;
	  parameterDeclaration->setNodeType(PARAMETER_DECLARATION);
	  parameterDeclaration->setDecompositionRule(1);
	  parameterDeclaration->declarationSpecifiers = $1.list;
	  parameterDeclaration->Declarator = $2.node;
	  $$.node = parameterDeclaration;
	}
  | declaration_specifiers abstract_declarator
    {
	  parameter_declaration* parameterDeclaration;
	  parameterDeclaration = new parameter_declaration;
	  parameterDeclaration->setNodeType(PARAMETER_DECLARATION);
	  parameterDeclaration->setDecompositionRule(2);
	  parameterDeclaration->declarationSpecifiers = $1.list;
	  parameterDeclaration->abstractDeclarator = $2.node;
	  $$.node = parameterDeclaration;
	}
  | declaration_specifiers
    {
	  parameter_declaration* parameterDeclaration;
	  parameterDeclaration = new parameter_declaration;
	  parameterDeclaration->setNodeType(PARAMETER_DECLARATION);
	  parameterDeclaration->setDecompositionRule(3);
	  parameterDeclaration->declarationSpecifiers = $1.list;
	  $$.node = parameterDeclaration;
	}
  | declaration_specifiers error	/* fixup missing parameter */
  ;

identifier_list
  : identifier_name
    {
	    identifier_list* identifierList;
	    identifierList = new identifier_list;
	    identifierList->setNodeType(IDENTIFIER_LIST);

	    identifierList->setCommaSeparated();
	    identifierList->addNodeLast($1.node);
	    $$.list = identifierList;
	  }
  | identifier_list op_comma identifier_name
    {
	    $1.list->addNodeLast($2.node);
	    $1.list->addNodeLast($3.node);
	    $$.list = $1.list;
	  }
  | error		/* insert missing identifier */
  ;

initializer
  : assignment_expression
    {
	  initializer* Initializer;
	  Initializer = new initializer;
	  Initializer->setNodeType(INITIALIZER);
	  Initializer->setDecompositionRule(1);
	  Initializer->assignmentExpression = $1.node;
	  $$.node = Initializer;
	}
  | open_c_br initializer_list close_c_br
    {
	  initializer* Initializer;
	  Initializer = new initializer;
	  Initializer->setNodeType(INITIALIZER);
	  Initializer->setDecompositionRule(2);
	  Initializer->openCBr = $1.list;
	  Initializer->initializerList = $2.list;
	  Initializer->closeCBr = $3.list;
	  $$.node = Initializer;
	}
  | open_c_br initializer_list op_comma close_c_br
    {
	  initializer* Initializer;
	  Initializer = new initializer;
	  Initializer->setNodeType(INITIALIZER);
	  Initializer->setDecompositionRule(3);
	  Initializer->openCBr = $1.list;
	  Initializer->initializerList = $2.list;
	  Initializer->Comma = $3.list;
	  Initializer->closeCBr = $4.list;
	  $$.node = Initializer;
	}
  ;

initializer_list
  : initializer
    {
	  initializer_list* initializerList;
	  initializerList = new initializer_list;
	  initializerList->setNodeType(INITIALIZER_LIST);
    initializerList->setCommaSeparated();
	  initializerList->addNodeLast($1.node);
	  $$.list = initializerList;
	}
  | initializer_list op_comma initializer
    {
	  $1.list->addNodeLast($2.node);	  
	  $1.list->addNodeLast($3.node);	  
	  $$.list = $1.list;
	}
  | error		/* fixup missing constant */
  ;

type_name
  : declaration_specifiers abstract_declarator
    {
	  type_name* typeName;
	  typeName = new type_name;
	  typeName->setNodeType(TYPE_NAME);
	  typeName->setDecompositionRule(1);
	  typeName->declarationSpecifiers = $1.node;
	  typeName->abstractDeclarator = $2.node;
	  $$.node = typeName;
	}
  | declaration_specifiers
    {
	  type_name* typeName;
	  typeName = new type_name;
	  typeName->setNodeType(TYPE_NAME);
	  typeName->setDecompositionRule(2);
	  typeName->declarationSpecifiers = $1.node;
	  $$.node = typeName;
	}
  ;

abstract_declarator
  : pointer
    {
	  abstract_declarator* abstractDeclarator;
	  abstractDeclarator = new abstract_declarator;
	  abstractDeclarator->setNodeType(ABSTRACT_DECLARATOR);
	  abstractDeclarator->setDecompositionRule(1);
	  abstractDeclarator->Pointer = $1.node;
	  $$.node = abstractDeclarator;
	}
  | pointer direct_abstract_declarator
    {
	  abstract_declarator* abstractDeclarator;
	  abstractDeclarator = new abstract_declarator;
	  abstractDeclarator->setNodeType(ABSTRACT_DECLARATOR);
	  abstractDeclarator->setDecompositionRule(2);
	  abstractDeclarator->Pointer = $1.node;
	  abstractDeclarator->directAbstractDeclarator = $2.node;
	  $$.node = abstractDeclarator;
	}
  |         direct_abstract_declarator
    {
	  abstract_declarator* abstractDeclarator;
	  abstractDeclarator = new abstract_declarator;
	  abstractDeclarator->setNodeType(ABSTRACT_DECLARATOR);
	  abstractDeclarator->setDecompositionRule(3);
	  abstractDeclarator->directAbstractDeclarator = $1.node;
	  $$.node = abstractDeclarator;
	}
  ;

direct_abstract_declarator
  : open_r_br abstract_declarator close_r_br
    {
	  direct_abstract_declarator* directAbstractDeclarator;
	  directAbstractDeclarator = new direct_abstract_declarator;
	  directAbstractDeclarator->setNodeType(DIRECT_ABSTRACT_DECLARATOR);
	  directAbstractDeclarator->setDecompositionRule(1);
    directAbstractDeclarator->openRBr = $1.node;
    directAbstractDeclarator->abstractDeclarator = $2.node;
    directAbstractDeclarator->closeRBr = $3.node;
	  $$.node = directAbstractDeclarator;
	}
  | direct_abstract_declarator open_s_br constant_expression close_s_br
    {
	  direct_abstract_declarator* directAbstractDeclarator;
	  directAbstractDeclarator = new direct_abstract_declarator;
	  directAbstractDeclarator->setNodeType(DIRECT_ABSTRACT_DECLARATOR);
	  directAbstractDeclarator->setDecompositionRule(2);
    directAbstractDeclarator->directAbstractDeclarator = $1.node;
    directAbstractDeclarator->openSBr = $2.node;
    directAbstractDeclarator->constantExpression = $3.node;
    directAbstractDeclarator->closeSBr = $4.node;
	  $$.node = directAbstractDeclarator;
	}
  | direct_abstract_declarator open_s_br                     close_s_br
    {
	  direct_abstract_declarator* directAbstractDeclarator;
	  directAbstractDeclarator = new direct_abstract_declarator;
	  directAbstractDeclarator->setNodeType(DIRECT_ABSTRACT_DECLARATOR);
	  directAbstractDeclarator->setDecompositionRule(3);
    directAbstractDeclarator->directAbstractDeclarator = $1.node;
    directAbstractDeclarator->openSBr = $2.node;
    directAbstractDeclarator->closeSBr = $3.node;
	  $$.node = directAbstractDeclarator;
	}
  |                            open_s_br constant_expression close_s_br
    {
	  direct_abstract_declarator* directAbstractDeclarator;
	  directAbstractDeclarator = new direct_abstract_declarator;
	  directAbstractDeclarator->setNodeType(DIRECT_ABSTRACT_DECLARATOR);
	  directAbstractDeclarator->setDecompositionRule(4);
    directAbstractDeclarator->openSBr = $1.node;
    directAbstractDeclarator->constantExpression = $2.node;
    directAbstractDeclarator->closeSBr = $3.node;
	  $$.node = directAbstractDeclarator;
	}
  |                            open_s_br                     close_s_br
    {
	  direct_abstract_declarator* directAbstractDeclarator;
	  directAbstractDeclarator = new direct_abstract_declarator;
	  directAbstractDeclarator->setNodeType(DIRECT_ABSTRACT_DECLARATOR);
	  directAbstractDeclarator->setDecompositionRule(5);
    directAbstractDeclarator->openSBr = $1.node;
    directAbstractDeclarator->closeSBr = $2.node;
	  $$.node = directAbstractDeclarator;
	}
  | direct_abstract_declarator open_r_br parameter_type_list close_r_br
    {
	  direct_abstract_declarator* directAbstractDeclarator;
	  directAbstractDeclarator = new direct_abstract_declarator;
	  directAbstractDeclarator->setNodeType(DIRECT_ABSTRACT_DECLARATOR);
	  directAbstractDeclarator->setDecompositionRule(6);
    directAbstractDeclarator->directAbstractDeclarator = $1.node;
    directAbstractDeclarator->openRBr = $2.node;
    directAbstractDeclarator->parameterTypeList = $3.node;
    directAbstractDeclarator->closeRBr = $4.node;
	  $$.node = directAbstractDeclarator;
	}
  | direct_abstract_declarator open_r_br                     close_r_br
    {
	  direct_abstract_declarator* directAbstractDeclarator;
	  directAbstractDeclarator = new direct_abstract_declarator;
	  directAbstractDeclarator->setNodeType(DIRECT_ABSTRACT_DECLARATOR);
	  directAbstractDeclarator->setDecompositionRule(7);
    directAbstractDeclarator->directAbstractDeclarator = $1.node;
    directAbstractDeclarator->openRBr = $2.node;
    directAbstractDeclarator->closeRBr = $3.node;
	  $$.node = directAbstractDeclarator;
	}
  |                            open_r_br parameter_type_list close_r_br
    {
	  direct_abstract_declarator* directAbstractDeclarator;
	  directAbstractDeclarator = new direct_abstract_declarator;
	  directAbstractDeclarator->setNodeType(DIRECT_ABSTRACT_DECLARATOR);
	  directAbstractDeclarator->setDecompositionRule(8);
    directAbstractDeclarator->openRBr = $1.node;
    directAbstractDeclarator->parameterTypeList = $2.node;
    directAbstractDeclarator->closeRBr = $3.node;
	  $$.node = directAbstractDeclarator;
	}
  |                            open_r_br                     close_r_br
    {
	  direct_abstract_declarator* directAbstractDeclarator;
	  directAbstractDeclarator = new direct_abstract_declarator;
	  directAbstractDeclarator->setNodeType(DIRECT_ABSTRACT_DECLARATOR);
	  directAbstractDeclarator->setDecompositionRule(9);
    directAbstractDeclarator->openRBr = $1.node;
    directAbstractDeclarator->closeRBr = $2.node;
	  $$.node = directAbstractDeclarator;
	}
  ;

statement
  : labeled_statement
    {
	  statement* Statement;
	  Statement = new statement;
	  Statement->setNodeType(STATEMENT);
	  Statement->setDecompositionRule(1);
	  Statement->labeledStatement = $1.node;
	  $$.node = Statement;
	}
  | expression_statement
    {
	  statement* Statement;
	  Statement = new statement;
	  Statement->setNodeType(STATEMENT);
	  Statement->setDecompositionRule(2);
	  Statement->expressionStatement = $1.node;
	  $$.node = Statement;
	}
  | compound_statement
    {
	  statement* Statement;
	  Statement = new statement;
	  Statement->setNodeType(STATEMENT);
	  Statement->setDecompositionRule(3);
	  Statement->compoundStatement = $1.node;
	  $$.node = Statement;
	}
  | selection_statement
    {
	  statement* Statement;
	  Statement = new statement;
	  Statement->setNodeType(STATEMENT);
	  Statement->setDecompositionRule(4);
	  Statement->selectionStatement = $1.node;
	  $$.node = Statement;
	}
  | iteration_statement
    {
	  statement* Statement;
	  Statement = new statement;
	  Statement->setNodeType(STATEMENT);
	  Statement->setDecompositionRule(5);
	  Statement->iterationStatement = $1.node;
	  $$.node = Statement;
	}
  | jump_statement
    {
	  statement* Statement;
	  Statement = new statement;
	  Statement->setNodeType(STATEMENT);
	  Statement->setDecompositionRule(6);
	  Statement->jumpStatement = $1.node;
	  $$.node = Statement;
	}
  | error semicolon		{ yyerrok; }	/* last ditch statement recovery */
  ;

labeled_statement
  : identifier_name colon statement
    {
      labeled_statement* labeledStatement;
      labeledStatement = new labeled_statement;
      labeledStatement->setNodeType(LABELED_STATEMENT);
      labeledStatement->setDecompositionRule(1);
      labeledStatement->Identifier = $1.node;
      labeledStatement->Colon = $2.node;
      labeledStatement->Statement = $3.node;
      $$.node = labeledStatement;
    }
  | keyword_Case constant_expression colon statement
    {
	    labeled_statement* labeledStatement;
	    labeledStatement = new labeled_statement;
	    labeledStatement->setNodeType(LABELED_STATEMENT);
	    labeledStatement->setDecompositionRule(2);
      labeledStatement->Keyword = $1.node;
      labeledStatement->constantExpression = $2.node;
      labeledStatement->Colon = $3.node;
      labeledStatement->Statement = $4.node;
	    $$.node = labeledStatement;
	}
  | keyword_Default colon statement
    {
	    labeled_statement* labeledStatement;
	    labeledStatement = new labeled_statement;
	    labeledStatement->setNodeType(LABELED_STATEMENT);
	    labeledStatement->setDecompositionRule(3);
      labeledStatement->Keyword = $1.node;
      labeledStatement->Colon = $2.node;
      labeledStatement->Statement = $3.node;
	    $$.node = labeledStatement;
	}
  ;

identifier_name
  : IDENTIFIER
    {
      identifier* Identifier;
      Identifier = new identifier(strlen($1.s));
      Identifier->setNodeType(IDENT);
      strcpy(Identifier->stringRepresentation, $1.s);
      Identifier->storeIgnored();
      $$.node = Identifier;
    }
  ;

expression_statement
  : expression semicolon
    {
	  expression_statement* expressionStatement;
	  expressionStatement = new expression_statement;
	  expressionStatement->setNodeType(EXPRESSION_STATEMENT);
	  expressionStatement->setDecompositionRule(1);
    expressionStatement->Expression = $1.node;
    expressionStatement->Semicolon = $2.node;
	  $$.node = expressionStatement;
	}
  |            semicolon
    {
	  expression_statement* expressionStatement;
	  expressionStatement = new expression_statement;
	  expressionStatement->setNodeType(EXPRESSION_STATEMENT);
	  expressionStatement->setDecompositionRule(2);
    expressionStatement->Semicolon = $1.node;
	  $$.node = expressionStatement;
	}
  ;

compound_statement
  : open_c_br declaration_list statement_list close_c_br
    {
	  compound_statement* compoundStatement;
	  compoundStatement = new compound_statement;
	  compoundStatement->setNodeType(COMPOUND_STATEMENT);
	  compoundStatement->setDecompositionRule(1);
	  compoundStatement->openCBr = $1.list;
	  compoundStatement->declarationList = $2.list;
	  compoundStatement->statementList = $3.list;
	  compoundStatement->closeCBr = $4.list;
	  $$.node = compoundStatement;
	}
  | open_c_br declaration_list                close_c_br
    {
	  compound_statement* compoundStatement;
	  compoundStatement = new compound_statement;
	  compoundStatement->setNodeType(COMPOUND_STATEMENT);
	  compoundStatement->setDecompositionRule(2);
	  compoundStatement->openCBr = $1.list;
	  compoundStatement->declarationList = $2.list;
	  compoundStatement->closeCBr = $3.list;
	  $$.node = compoundStatement;
	}
  | open_c_br                  statement_list close_c_br
    {
	  compound_statement* compoundStatement;
	  compoundStatement = new compound_statement;
	  compoundStatement->setNodeType(COMPOUND_STATEMENT);
	  compoundStatement->setDecompositionRule(3);
	  compoundStatement->openCBr = $1.list;
	  compoundStatement->statementList = $2.list;
	  compoundStatement->closeCBr = $3.list;
	  $$.node = compoundStatement;
	}
  | open_c_br                                 close_c_br
    {
	  compound_statement* compoundStatement;
	  compoundStatement = new compound_statement;
	  compoundStatement->setNodeType(COMPOUND_STATEMENT);
	  compoundStatement->setDecompositionRule(4);
	  compoundStatement->openCBr = $1.list;
	  compoundStatement->closeCBr = $2.list;
	  $$.node = compoundStatement;
	}
  ;

statement_list
  : statement
    {
	  statement_list* statementList;
	  statementList = new statement_list;
	  statementList->setNodeType(STATEMENT_LIST);
    statementList->setNewlineSeparated();
	  statementList->addNodeLast($1.node);
	  $$.list = statementList;
	}
  | statement_list statement
    {
	  $1.list->addNodeLast($2.node);
	  $$.list = $1.list;
	}
  ;

selection_statement
  : keyword_If open_r_br expression close_r_br statement
    {
	  selection_statement* selectionStatement;
	  selectionStatement = new selection_statement;
	  selectionStatement->setNodeType(SELECTION_STATEMENT);
	  selectionStatement->setDecompositionRule(1);
    selectionStatement->keywordIf = $1.node;
    selectionStatement->openRBr = $2.node;
    selectionStatement->Expression = $3.node;
    selectionStatement->closeRBr = $4.node;
    selectionStatement->Statement = $5.node;
    $$.node = selectionStatement;

	}
  | keyword_If open_r_br expression close_r_br statement keyword_Else statement
    {
	  selection_statement* selectionStatement;
	  selectionStatement = new selection_statement;
	  selectionStatement->setNodeType(SELECTION_STATEMENT);
	  selectionStatement->setDecompositionRule(2);
    selectionStatement->keywordIf = $1.node;
    selectionStatement->openRBr = $2.node;
    selectionStatement->Expression = $3.node;
    selectionStatement->closeRBr = $4.node;
    selectionStatement->Statement = $5.node;
    selectionStatement->keywordElse = $6.node;
    selectionStatement->elseStatement = $7.node;
	  $$.node = selectionStatement;
	}
  | keyword_Switch open_r_br expression close_r_br statement
    {
	  selection_statement* selectionStatement;
	  selectionStatement = new selection_statement;
	  selectionStatement->setNodeType(SELECTION_STATEMENT);
	  selectionStatement->setDecompositionRule(3);
    selectionStatement->keywordIf = $1.node;
    selectionStatement->openRBr = $2.node;
    selectionStatement->Expression = $3.node;
    selectionStatement->closeRBr = $4.node;
    selectionStatement->Statement = $5.node;
	  $$.node = selectionStatement;
	}
  ;

iteration_statement
  : keyword_While open_r_br expression close_r_br statement
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(1);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->openRBr = $2.node;
    iterationStatement->Expression = $3.node;
    iterationStatement->closeRBr = $4.node;
    iterationStatement->Statement = $5.node;
	  $$.node = iterationStatement;
	}
  | keyword_Do statement keyword_While open_r_br expression close_r_br semicolon
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(2);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->Statement = $2.node;
    iterationStatement->Keyword2 = $3.node;
    iterationStatement->openRBr = $4.node;
    iterationStatement->Expression = $5.node;
    iterationStatement->closeRBr = $6.node;
    iterationStatement->Semicolon1 = $7.node;
	  $$.node = iterationStatement;
	}
  | keyword_For open_r_br expression semicolon expression semicolon expression close_r_br statement
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(3);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->openRBr = $2.node;
    iterationStatement->initExpression = $3.node;
    iterationStatement->Semicolon1 = $4.node;
    iterationStatement->Expression = $5.node;
    iterationStatement->Semicolon2 = $6.node;
    iterationStatement->iterExpression = $7.node;
    iterationStatement->closeRBr = $8.node;
    iterationStatement->Statement = $9.node;
	  $$.node = iterationStatement;
	}
  | keyword_For open_r_br expression semicolon expression semicolon            close_r_br statement
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(4);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->openRBr = $2.node;
    iterationStatement->initExpression = $3.node;
    iterationStatement->Semicolon1 = $4.node;
    iterationStatement->Expression = $5.node;
    iterationStatement->Semicolon2 = $6.node;
    iterationStatement->closeRBr = $7.node;
    iterationStatement->Statement = $8.node;
	  $$.node = iterationStatement;
	}
  | keyword_For open_r_br expression semicolon            semicolon expression close_r_br statement
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(5);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->openRBr = $2.node;
    iterationStatement->initExpression = $3.node;
    iterationStatement->Semicolon1 = $4.node;
    iterationStatement->Semicolon2 = $5.node;
    iterationStatement->iterExpression = $6.node;
    iterationStatement->closeRBr = $7.node;
    iterationStatement->Statement = $8.node;
	  $$.node = iterationStatement;
	}
  | keyword_For open_r_br expression semicolon            semicolon            close_r_br statement
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(6);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->openRBr = $2.node;
    iterationStatement->initExpression = $3.node;
    iterationStatement->Semicolon1 = $4.node;
    iterationStatement->Semicolon2 = $5.node;
    iterationStatement->closeRBr = $6.node;
    iterationStatement->Statement = $7.node;
	  $$.node = iterationStatement;
	}
  | keyword_For open_r_br            semicolon expression semicolon expression close_r_br statement
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(7);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->openRBr = $2.node;
    iterationStatement->Semicolon1 = $3.node;
    iterationStatement->Expression = $4.node;
    iterationStatement->Semicolon2 = $5.node;
    iterationStatement->iterExpression = $6.node;
    iterationStatement->closeRBr = $7.node;
    iterationStatement->Statement = $8.node;
	  $$.node = iterationStatement;
	}
  | keyword_For open_r_br            semicolon expression semicolon            close_r_br statement
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(8);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->openRBr = $2.node;
    iterationStatement->Semicolon1 = $3.node;
    iterationStatement->Expression = $4.node;
    iterationStatement->Semicolon2 = $5.node;
    iterationStatement->closeRBr = $6.node;
    iterationStatement->Statement = $7.node;
	  $$.node = iterationStatement;
	}
  | keyword_For open_r_br            semicolon            semicolon expression close_r_br statement
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(9);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->openRBr = $2.node;
    iterationStatement->Semicolon1 = $3.node;
    iterationStatement->Semicolon2 = $4.node;
    iterationStatement->iterExpression = $5.node;
    iterationStatement->closeRBr = $6.node;
    iterationStatement->Statement = $7.node;
	  $$.node = iterationStatement;
	}
  | keyword_For open_r_br            semicolon            semicolon            close_r_br statement
    {
	  iteration_statement* iterationStatement;
	  iterationStatement = new iteration_statement;
	  iterationStatement->setNodeType(ITERATION_STATEMENT);
	  iterationStatement->setDecompositionRule(10);
    iterationStatement->Keyword1 = $1.node;
    iterationStatement->openRBr = $2.node;
    iterationStatement->Semicolon1 = $3.node;
    iterationStatement->Semicolon2 = $4.node;
    iterationStatement->closeRBr = $5.node;
    iterationStatement->Statement = $6.node;
	  $$.node = iterationStatement;
	}
	/* fixup error in for expression list */
  | keyword_For open_r_br error				     close_r_br statement
  ;

jump_statement
  : keyword_Goto identifier_name   semicolon
    {
	  jump_statement* jumpStatement;
	  jumpStatement = new jump_statement;
	  jumpStatement->setNodeType(JUMP_STATEMENT);
	  jumpStatement->setDecompositionRule(1);
    jumpStatement->Keyword = $1.node;
    jumpStatement->Identifier = $2.node;
    jumpStatement->Semicolon = $3.node;
	  $$.node = jumpStatement;
	}
  | keyword_Continue          semicolon
    {
	  jump_statement* jumpStatement;
	  jumpStatement = new jump_statement;
	  jumpStatement->setNodeType(JUMP_STATEMENT);
	  jumpStatement->setDecompositionRule(2);
    jumpStatement->Keyword = $1.node;
    jumpStatement->Semicolon = $2.node;
	  $$.node = jumpStatement;
	}
  | keyword_Break             semicolon
    {
	  jump_statement* jumpStatement;
	  jumpStatement = new jump_statement;
	  jumpStatement->setNodeType(JUMP_STATEMENT);
	  jumpStatement->setDecompositionRule(3);
    jumpStatement->Keyword = $1.node;
    jumpStatement->Semicolon = $2.node;
	  $$.node = jumpStatement;
	}
  | keyword_Return expression semicolon
    {
	  jump_statement* jumpStatement;
	  jumpStatement = new jump_statement;
	  jumpStatement->setNodeType(JUMP_STATEMENT);
	  jumpStatement->setDecompositionRule(4);
    jumpStatement->Keyword = $1.node;
    jumpStatement->Expression = $2.node;
    jumpStatement->Semicolon = $3.node;
    $$.node = jumpStatement;
	}
  | keyword_Return            semicolon
    {
	  jump_statement* jumpStatement;
	  jumpStatement = new jump_statement;
	  jumpStatement->setNodeType(JUMP_STATEMENT);
	  jumpStatement->setDecompositionRule(5);
    jumpStatement->Keyword = $1.node;
    jumpStatement->Semicolon = $2.node;
	  $$.node = jumpStatement;
	}
  ;

expression
  : assignment_expression
    {
      expression* Expression;
      Expression = new expression;
      Expression->setNodeType(EXPRESSION);
      Expression->setDecompositionRule(1);
      Expression->assignmentExpression = $1.node;
      $$.node = Expression;
    }
  | expression op_comma assignment_expression
    {
      expression* Expression;
      Expression = new expression;
      Expression->setNodeType(EXPRESSION);
      Expression->setDecompositionRule(2);
      Expression->Expression = $1.node;
      Expression->Comma = $2.node;
      Expression->assignmentExpression = $3.node;
      $$.node = Expression;
    }
  | expression error assignment_expression     /* lowest precedence infix op */
  ;

assignment_expression
  : conditional_expression
    {
	  assignment_expression* assignmentExpression;
	  assignmentExpression = new assignment_expression;
	  assignmentExpression->setNodeType(ASSIGNMENT_EXPRESSION);
	  assignmentExpression->setDecompositionRule(1);
    assignmentExpression->conditionalExpression = $1.node;
	  $$.node = assignmentExpression;
	}
  | unary_expression assignment_operator assignment_expression
    {
	  assignment_expression* assignmentExpression;
	  assignmentExpression = new assignment_expression;
	  assignmentExpression->setNodeType(ASSIGNMENT_EXPRESSION);
	  assignmentExpression->setDecompositionRule(2);
    assignmentExpression->unaryExpression = $1.node;
    assignmentExpression->assignmentOperator = $2.node;
    assignmentExpression->assignmentExpression = $3.node;
	  $$.node = assignmentExpression;
	}
  ;

assignment_operator
  : '='
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(1);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | MULEQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(2);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | DIVEQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(3);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | MODEQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(4);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | ADDEQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(5);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | SUBEQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(6);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | SHLEQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(7);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | SHREQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(8);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | ANDEQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(9);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | IOREQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(10);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  | XOREQ
    {
      assignment_operator* assignmentOperator;
      assignmentOperator = new assignment_operator;
      assignmentOperator->setNodeType(ASSIGNMENT_OPERATOR);
      assignmentOperator->setDecompositionRule(11);
      assignmentOperator->storeIgnored();
      $$.node = assignmentOperator;
    }
  ;

conditional_expression
  : logical_or_expression
    {
      conditional_expression* conditionalExpression;
      conditionalExpression = new conditional_expression;
      conditionalExpression->setNodeType(CONDITIONAL_EXPRESSION);
      conditionalExpression->setDecompositionRule(1);
      conditionalExpression->logicalOrExpression = $1.node;
      $$.node = conditionalExpression;
    }
  | logical_or_expression ask expression colon conditional_expression
    {
      conditional_expression* conditionalExpression;
      conditionalExpression = new conditional_expression;
      conditionalExpression->setNodeType(CONDITIONAL_EXPRESSION);
      conditionalExpression->setDecompositionRule(2);
      conditionalExpression->logicalOrExpression = $1.node;
      conditionalExpression->Ask = $2.node;
      conditionalExpression->Expression = $3.node;
      conditionalExpression->Colon = $4.node;
      conditionalExpression->conditionalExpression = $5.node;
      $$.node = conditionalExpression;
    }
  ;

constant_expression
  : conditional_expression
    {
	  constant_expression* constantExpression;
	  constantExpression = new constant_expression;
	  constantExpression->setNodeType(CONSTANT_EXPRESSION);
	  constantExpression->setDecompositionRule(1); // =)
    constantExpression->conditionalExpression = $1.node;
	  $$.node = constantExpression;
	}
  ;

logical_or_expression
  : logical_and_expression
    {
      logical_or_expression* logicalOrExpression;
      logicalOrExpression = new logical_or_expression;
      logicalOrExpression->setNodeType(LOGICAL_OR_EXPRESSION);
      logicalOrExpression->setDecompositionRule(1);
      logicalOrExpression->logicalAndExpression = $1.node;
      $$.node = logicalOrExpression;
    }
  | logical_or_expression op_oror logical_and_expression
    {
      logical_or_expression* logicalOrExpression;
      logicalOrExpression = new logical_or_expression;
      logicalOrExpression->setNodeType(LOGICAL_OR_EXPRESSION);
      logicalOrExpression->setDecompositionRule(2);
      logicalOrExpression->logicalOrExpression = $1.node;
      logicalOrExpression->Operator = $2.node;
      logicalOrExpression->logicalAndExpression = $3.node;
      $$.node = logicalOrExpression;
    }
  ;

logical_and_expression
  : inclusive_or_expression
    {
      logical_and_expression* logicalAndExpression;
      logicalAndExpression = new logical_and_expression;
      logicalAndExpression->setNodeType(LOGICAL_AND_EXPRESSION);
      logicalAndExpression->setDecompositionRule(1);
      logicalAndExpression->inclusiveOrExpression = $1.node;
      $$.node = logicalAndExpression;
    }
  | logical_and_expression op_andand inclusive_or_expression
    {
      logical_and_expression* logicalAndExpression;
      logicalAndExpression = new logical_and_expression;
      logicalAndExpression->setNodeType(LOGICAL_AND_EXPRESSION);
      logicalAndExpression->setDecompositionRule(2);
      logicalAndExpression->logicalAndExpression = $1.node;
      logicalAndExpression->Operator = $2.node;
      logicalAndExpression->inclusiveOrExpression = $3.node;
      $$.node = logicalAndExpression;
    }
  ;

inclusive_or_expression
  : exclusive_or_expression
    {
      inclusive_or_expression* inclusiveOrExpression;
      inclusiveOrExpression = new inclusive_or_expression;
      inclusiveOrExpression->setNodeType(INCLUSIVE_OR_EXPRESSION);
      inclusiveOrExpression->setDecompositionRule(1);
      inclusiveOrExpression->exclusiveOrExpression = $1.node;
      $$.node = inclusiveOrExpression;
    }
  | inclusive_or_expression op_or exclusive_or_expression
    {
      inclusive_or_expression* inclusiveOrExpression;
      inclusiveOrExpression = new inclusive_or_expression;
      inclusiveOrExpression->setNodeType(INCLUSIVE_OR_EXPRESSION);
      inclusiveOrExpression->setDecompositionRule(2);
      inclusiveOrExpression->inclusiveOrExpression = $1.node;
      inclusiveOrExpression->Operator = $2.node;
      inclusiveOrExpression->exclusiveOrExpression = $3.node;
      $$.node = inclusiveOrExpression;
    }
  ;

exclusive_or_expression
  : and_expression
    {
      exclusive_or_expression* exclusiveOrExpression;
      exclusiveOrExpression = new exclusive_or_expression;
      exclusiveOrExpression->setNodeType(EXCLUSIVE_OR_EXPRESSION);
      exclusiveOrExpression->setDecompositionRule(1);
      exclusiveOrExpression->andExpression = $1.node;
      $$.node = exclusiveOrExpression;
    }
  | exclusive_or_expression op_xor and_expression
    {
      exclusive_or_expression* exclusiveOrExpression;
      exclusiveOrExpression = new exclusive_or_expression;
      exclusiveOrExpression->setNodeType(EXCLUSIVE_OR_EXPRESSION);
      exclusiveOrExpression->setDecompositionRule(2);
      exclusiveOrExpression->exclusiveOrExpression = $1.node;
      exclusiveOrExpression->Operator = $2.node;
      exclusiveOrExpression->andExpression = $3.node;
      $$.node = exclusiveOrExpression;
    }
  ;

and_expression
  : equality_expression
    {
      and_expression* andExpression;
      andExpression = new and_expression;
      andExpression->setNodeType(AND_EXPRESSION);
      andExpression->setDecompositionRule(1);
      andExpression->equalityExpression = $1.node;
      $$.node = andExpression;
    }
  | and_expression op_and equality_expression
    {
      and_expression* andExpression;
      andExpression = new and_expression;
      andExpression->setNodeType(AND_EXPRESSION);
      andExpression->setDecompositionRule(2);
      andExpression->andExpression = $1.node;
      andExpression->Operator = $2.node;
      andExpression->equalityExpression = $3.node;
      $$.node = andExpression;
    }
  ;

equality_expression
  : relational_expression
    {
      equality_expression* equalityExpression;
      equalityExpression = new equality_expression;
      equalityExpression->setNodeType(EQUALITY_EXPRESSION);
      equalityExpression->setDecompositionRule(1);
      equalityExpression->relationalExpression = $1.node;
      $$.node = equalityExpression;
    }
  | equality_expression op_equ  relational_expression
    {
      equality_expression* equalityExpression;
      equalityExpression = new equality_expression;
      equalityExpression->setNodeType(EQUALITY_EXPRESSION);
      equalityExpression->setDecompositionRule(2);
      equalityExpression->equalityExpression = $1.node;
      equalityExpression->Operator = $2.node;
      equalityExpression->relationalExpression = $3.node;
      $$.node = equalityExpression;
    }
  | equality_expression op_nequ relational_expression
    {
      equality_expression* equalityExpression;
      equalityExpression = new equality_expression;
      equalityExpression->setNodeType(EQUALITY_EXPRESSION);
      equalityExpression->setDecompositionRule(3);
      equalityExpression->equalityExpression = $1.node;
      equalityExpression->Operator = $2.node;
      equalityExpression->relationalExpression = $3.node;
      $$.node = equalityExpression;
    }
  ;

relational_expression
  : shift_expression
    {
      relational_expression* relationalExpression;
      relationalExpression = new relational_expression;
      relationalExpression->setNodeType(RELATIONAL_EXPRESSION);
      relationalExpression->setDecompositionRule(1);
      relationalExpression->shiftExpression = $1.node;
      $$.node = relationalExpression;
    }
  | relational_expression op_less shift_expression
    {
      relational_expression* relationalExpression;
      relationalExpression = new relational_expression;
      relationalExpression->setNodeType(RELATIONAL_EXPRESSION);
      relationalExpression->setDecompositionRule(2);
	    relationalExpression->relationalExpression = $1.node;
      relationalExpression->Operator = $2.node;
	    relationalExpression->shiftExpression = $3.node;
      $$.node = relationalExpression;
    }
  | relational_expression op_greater shift_expression
    {
      relational_expression* relationalExpression;
      relationalExpression = new relational_expression;
      relationalExpression->setNodeType(RELATIONAL_EXPRESSION);
      relationalExpression->setDecompositionRule(3);
      relationalExpression->relationalExpression = $1.node;
      relationalExpression->Operator = $2.node;
      relationalExpression->shiftExpression = $3.node;
      $$.node = relationalExpression;
    }
  | relational_expression op_leq shift_expression
    {
      relational_expression* relationalExpression;
      relationalExpression = new relational_expression;
      relationalExpression->setNodeType(RELATIONAL_EXPRESSION);
      relationalExpression->setDecompositionRule(4);
      relationalExpression->relationalExpression = $1.node;
      relationalExpression->Operator = $2.node;
      relationalExpression->shiftExpression = $3.node;
      $$.node = relationalExpression;
    }
  | relational_expression op_geq shift_expression
    {
      relational_expression* relationalExpression;
      relationalExpression = new relational_expression;
      relationalExpression->setNodeType(RELATIONAL_EXPRESSION);
      relationalExpression->setDecompositionRule(5);
      relationalExpression->relationalExpression = $1.node;
      relationalExpression->Operator = $2.node;
      relationalExpression->shiftExpression = $3.node;
      $$.node = relationalExpression;
    }
  ;
			     
shift_expression
  : additive_expression
    {
	    shift_expression* shiftExpression;
	    shiftExpression = new shift_expression;
	    shiftExpression->setNodeType(SHIFT_EXPRESSION);
	    shiftExpression->setDecompositionRule(1);
	    shiftExpression->additiveExpression = $1.node;
	  $$.node = shiftExpression;
	}
  | shift_expression op_shl additive_expression
    {
	    shift_expression* shiftExpression;
	    shiftExpression = new shift_expression;
	    shiftExpression->setNodeType(SHIFT_EXPRESSION);
	    shiftExpression->setDecompositionRule(2);
	    shiftExpression->shiftExpression = $1.node;
      shiftExpression->Operator = $2.node;
	    shiftExpression->additiveExpression = $3.node;
	  $$.node = shiftExpression;
	}
  | shift_expression op_shr additive_expression
    {
	    shift_expression* shiftExpression;
	    shiftExpression = new shift_expression;
	    shiftExpression->setNodeType(SHIFT_EXPRESSION);
	    shiftExpression->setDecompositionRule(3);
	    shiftExpression->shiftExpression = $1.node;
      shiftExpression->Operator = $2.node;
	    shiftExpression->additiveExpression = $3.node;
	    $$.node = shiftExpression;
	}
  ;

additive_expression
  : multiplicative_expression
    {
	    additive_expression* additiveExpression;
	    additiveExpression = new additive_expression;
	    additiveExpression->setNodeType(ADDITIVE_EXPRESSION);
	    additiveExpression->setDecompositionRule(1);
	    additiveExpression->multiplicativeExpression = $1.node;
	    $$.node = additiveExpression;
	  }
  | additive_expression op_plus multiplicative_expression
    {
	    additive_expression* additiveExpression;
	    additiveExpression = new additive_expression;
	    additiveExpression->setNodeType(ADDITIVE_EXPRESSION);
	    additiveExpression->setDecompositionRule(2);
	    additiveExpression->additiveExpression = $1.node;
      additiveExpression->Operator = $2.node;
	    additiveExpression->multiplicativeExpression = $3.node;
	    $$.node = additiveExpression;
	  }
  | additive_expression op_minus multiplicative_expression
    {
	    additive_expression* additiveExpression;
	    additiveExpression = new additive_expression;
	    additiveExpression->setNodeType(ADDITIVE_EXPRESSION);
	    additiveExpression->setDecompositionRule(3);
	    additiveExpression->additiveExpression = $1.node;
      additiveExpression->Operator = $2.node;
	    additiveExpression->multiplicativeExpression = $3.node;
	    $$.node = additiveExpression;
	  }
  ; 

multiplicative_expression
  : cast_expression
    {
	    multiplicative_expression* multiplicativeExpression;
	    multiplicativeExpression = new multiplicative_expression;
	    multiplicativeExpression->setNodeType(MULTIPLICATIVE_EXPRESSION);
	    multiplicativeExpression->setDecompositionRule(1);
	    multiplicativeExpression->castExpression = $1.node;
	    $$.node = multiplicativeExpression;
	  }
  | multiplicative_expression asterisk cast_expression
    {
	    multiplicative_expression* multiplicativeExpression;
	    multiplicativeExpression = new multiplicative_expression;
	    multiplicativeExpression->setNodeType(MULTIPLICATIVE_EXPRESSION);
	    multiplicativeExpression->setDecompositionRule(2);
	    multiplicativeExpression->multiplicativeExpression = $1.node;
      multiplicativeExpression->Operator = $2.node;
	    multiplicativeExpression->castExpression = $3.node;
	    $$.node = multiplicativeExpression;
	  }
  | multiplicative_expression op_div cast_expression
    {
	    multiplicative_expression* multiplicativeExpression;
	    multiplicativeExpression = new multiplicative_expression;
	    multiplicativeExpression->setNodeType(MULTIPLICATIVE_EXPRESSION);
	    multiplicativeExpression->setDecompositionRule(3);
	    multiplicativeExpression->multiplicativeExpression = $1.node;
      multiplicativeExpression->Operator = $2.node;
	    multiplicativeExpression->castExpression = $3.node;
	    $$.node = multiplicativeExpression;
	  }
  | multiplicative_expression op_mod cast_expression
    {
	    multiplicative_expression* multiplicativeExpression;
	    multiplicativeExpression = new multiplicative_expression;
	    multiplicativeExpression->setNodeType(MULTIPLICATIVE_EXPRESSION);
	    multiplicativeExpression->setDecompositionRule(4);
	    multiplicativeExpression->multiplicativeExpression = $1.node;
      multiplicativeExpression->Operator = $2.node;
	    multiplicativeExpression->castExpression = $3.node;
	    $$.node = multiplicativeExpression;
	  }
  ; 

cast_expression
  : unary_expression
    {
	    cast_expression* castExpression;
	    castExpression = new cast_expression;
	    castExpression->setNodeType(CAST_EXPRESSION);
	    castExpression->setDecompositionRule(1);
	    castExpression->unaryExpression = $1.node;
	    $$.node = castExpression;
	  }
  | open_r_br type_name close_r_br cast_expression
    {
	    cast_expression* castExpression;
	    castExpression = new cast_expression;
	    castExpression->setNodeType(CAST_EXPRESSION);
	    castExpression->setDecompositionRule(1);
	    castExpression->openRBr = $1.node;
	    castExpression->typeName = $2.node;
	    castExpression->closeRBr = $3.node;
	    castExpression->castExpression = $4.node;
	    $$.node = castExpression;
	  }
  ;

unary_expression
  : postfix_expression
    {
      unary_expression* unaryExpression;
      unaryExpression = new unary_expression;
      unaryExpression->setNodeType(UNARY_EXPRESSION);
      unaryExpression->setDecompositionRule(1);
      unaryExpression->postfixExpression = $1.node;
      $$.node = unaryExpression;
    }
  | op_addadd unary_expression
    {
      unary_expression* unaryExpression;
      unaryExpression = new unary_expression;
      unaryExpression->setNodeType(UNARY_EXPRESSION);
      unaryExpression->setDecompositionRule(2);
      unaryExpression->Operator = $1.node;
      unaryExpression->unaryExpression = $2.node;
      $$.node = unaryExpression;
    }
  | op_subsub unary_expression
    {
      unary_expression* unaryExpression;
      unaryExpression = new unary_expression;
      unaryExpression->setNodeType(UNARY_EXPRESSION);
      unaryExpression->setDecompositionRule(3);
      unaryExpression->Operator = $1.node;
      unaryExpression->unaryExpression = $2.node;
      $$.node = unaryExpression;
    }
  | unary_operator cast_expression
    {
      unary_expression* unaryExpression;
      unaryExpression = new unary_expression;
      unaryExpression->setNodeType(UNARY_EXPRESSION);
      unaryExpression->setDecompositionRule(4);
      unaryExpression->unaryOperator = $1.node;
      unaryExpression->castExpression = $2.node;
      $$.node = unaryExpression;
    }
  | keyword_Sizeof unary_expression
    {
      unary_expression* unaryExpression;
      unaryExpression = new unary_expression;
      unaryExpression->setNodeType(UNARY_EXPRESSION);
      unaryExpression->setDecompositionRule(5);
      unaryExpression->Keyword = $1.node;
      unaryExpression->unaryExpression = $2.node;
      $$.node = unaryExpression;
    }
  | keyword_Sizeof open_r_br type_name close_r_br
    {
      unary_expression* unaryExpression;
      unaryExpression = new unary_expression;
      unaryExpression->setNodeType(UNARY_EXPRESSION);
      unaryExpression->setDecompositionRule(6);
      unaryExpression->Keyword = $1.node;
      unaryExpression->openRBr = $2.node;
      unaryExpression->typeName = $3.node;
      unaryExpression->closeRBr = $2.node;
      $$.node = unaryExpression;
    }
  ;

unary_operator
  : '&'
    {
	  unary_operator* unaryOperator;
	  unaryOperator = new unary_operator;
	  unaryOperator->setNodeType(UNARY_OPERATOR);
	  unaryOperator->setDecompositionRule(1);
    unaryOperator->storeIgnored();
	  $$.node = unaryOperator;
	}
  | '*'
    {
	  unary_operator* unaryOperator;
	  unaryOperator = new unary_operator;
	  unaryOperator->setNodeType(UNARY_OPERATOR);
	  unaryOperator->setDecompositionRule(2);
    unaryOperator->storeIgnored();
	  $$.node = unaryOperator;
	}
  | '+'
    {
	  unary_operator* unaryOperator;
	  unaryOperator = new unary_operator;
	  unaryOperator->setNodeType(UNARY_OPERATOR);
	  unaryOperator->setDecompositionRule(3);
    unaryOperator->storeIgnored();
	  $$.node = unaryOperator;
	}
  | '-'
    {
	  unary_operator* unaryOperator;
	  unaryOperator = new unary_operator;
	  unaryOperator->setNodeType(UNARY_OPERATOR);
	  unaryOperator->setDecompositionRule(4);
    unaryOperator->storeIgnored();
	  $$.node = unaryOperator;
	}
  | '~'
    {
	  unary_operator* unaryOperator;
	  unaryOperator = new unary_operator;
	  unaryOperator->setNodeType(UNARY_OPERATOR);
	  unaryOperator->setDecompositionRule(5);
    unaryOperator->storeIgnored();
	  $$.node = unaryOperator;
	}
  | '!'
    {
	  unary_operator* unaryOperator;
	  unaryOperator = new unary_operator;
	  unaryOperator->setNodeType(UNARY_OPERATOR);
	  unaryOperator->setDecompositionRule(6);
    unaryOperator->storeIgnored();
	  $$.node = unaryOperator;
	}
  ;

postfix_expression
  : primary_expression
    {
	  postfix_expression* postfixExpression;
	  postfixExpression = new postfix_expression;
	  postfixExpression->setNodeType(POSTFIX_EXPRESSION);
	  postfixExpression->setDecompositionRule(1);
	  postfixExpression->primaryExpression = $1.node;
	  $$.node = postfixExpression;
	}
  | postfix_expression open_s_br expression close_s_br
    {
	  postfix_expression* postfixExpression;
	  postfixExpression = new postfix_expression;
	  postfixExpression->setNodeType(POSTFIX_EXPRESSION);
	  postfixExpression->setDecompositionRule(2);
	  postfixExpression->postfixExpression = $1.node;
	  postfixExpression->openSBr = $2.node;
	  postfixExpression->Expression = $3.node;
	  postfixExpression->closeSBr = $4.node;
	  $$.node = postfixExpression;
	}
  | postfix_expression open_r_br argument_expression_list close_r_br
    {
	  postfix_expression* postfixExpression;
	  postfixExpression = new postfix_expression;
	  postfixExpression->setNodeType(POSTFIX_EXPRESSION);
	  postfixExpression->setDecompositionRule(3);
	  postfixExpression->postfixExpression = $1.node;
	  postfixExpression->openRBr = $2.node;
	  postfixExpression->argumentExpressionList = $3.node;
	  postfixExpression->closeRBr = $4.node;
	  $$.node = postfixExpression;
	}
  | postfix_expression open_r_br                          close_r_br
    {
	  postfix_expression* postfixExpression;
	  postfixExpression = new postfix_expression;
	  postfixExpression->setNodeType(POSTFIX_EXPRESSION);
	  postfixExpression->setDecompositionRule(4);
	  postfixExpression->postfixExpression = $1.node;
	  postfixExpression->openRBr = $2.node;
	  postfixExpression->closeRBr = $3.node;
	  $$.node = postfixExpression;
	}
  | postfix_expression op_dot identifier_name
    {
	  postfix_expression* postfixExpression;
	  postfixExpression = new postfix_expression;
	  postfixExpression->setNodeType(POSTFIX_EXPRESSION);
	  postfixExpression->setDecompositionRule(5);
	  postfixExpression->postfixExpression = $1.node;
	  postfixExpression->Operator = $2.node;
	  postfixExpression->Identifier = $3.node;
	  $$.node = postfixExpression;
	}
  | postfix_expression op_ptr identifier_name
    {
	  postfix_expression* postfixExpression;
	  postfixExpression = new postfix_expression;
	  postfixExpression->setNodeType(POSTFIX_EXPRESSION);
	  postfixExpression->setDecompositionRule(6);
	  postfixExpression->postfixExpression = $1.node;
	  postfixExpression->Operator = $2.node;
	  postfixExpression->Identifier = $3.node;
	  $$.node = postfixExpression;
	}
  | postfix_expression op_addadd
    {
	  postfix_expression* postfixExpression;
	  postfixExpression = new postfix_expression;
	  postfixExpression->setNodeType(POSTFIX_EXPRESSION);
	  postfixExpression->setDecompositionRule(7);
	  postfixExpression->postfixExpression = $1.node;
	  postfixExpression->Operator = $2.node;
	  $$.node = postfixExpression;
	}
  | postfix_expression op_subsub
    {
	  postfix_expression* postfixExpression;
	  postfixExpression = new postfix_expression;
	  postfixExpression->setNodeType(POSTFIX_EXPRESSION);
	  postfixExpression->setDecompositionRule(8);
	  postfixExpression->postfixExpression = $1.node;
	  postfixExpression->Operator = $2.node;
	  $$.node = postfixExpression;
	}
  ;

primary_expression
  : identifier_name
    {
	  primary_expression* primaryExpression;
	  primaryExpression = new primary_expression;
	  primaryExpression->setNodeType(PRIMARY_EXPRESSION);
	  primaryExpression->setDecompositionRule(1);
    primaryExpression->Identifier = $1.node;
	  $$.node = primaryExpression;
	}
  | constant
    {
	  primary_expression* primaryExpression;
	  primaryExpression = new primary_expression;
	  primaryExpression->setNodeType(PRIMARY_EXPRESSION);
	  primaryExpression->setDecompositionRule(2);
    primaryExpression->Constant = $1.node;
	  $$.node = primaryExpression;
	}
  | string_name
    {
	  primary_expression* primaryExpression;
	  primaryExpression = new primary_expression;
	  primaryExpression->setNodeType(PRIMARY_EXPRESSION);
	  primaryExpression->setDecompositionRule(3);
    primaryExpression->String = $1.node;
	  $$.node = primaryExpression;
	}
  | open_r_br expression close_r_br
    {
	  primary_expression* primaryExpression;
	  primaryExpression = new primary_expression;
	  primaryExpression->setNodeType(PRIMARY_EXPRESSION);
	  primaryExpression->setDecompositionRule(4);
    primaryExpression->openRBr = $1.node;
    primaryExpression->Expression = $2.node;
    primaryExpression->closeRBr = $1.node;
	  $$.node = primaryExpression;
	}
  ;

string_name
  : STRING
    {
      string* String;
      String = new string(strlen($1.s));
      String->setNodeType(STRNG);
      strcpy(String->stringRepresentation, $1.s);
      String->storeIgnored();
      $$.node = String;
    }
  ;

argument_expression_list
  : assignment_expression
    {
      argument_expression_list* argumentExpressionList;
      argumentExpressionList = new argument_expression_list;
      argumentExpressionList->setNodeType(ARGUMENT_EXPRESSION_LIST);
      argumentExpressionList->setCommaSeparated();
      argumentExpressionList->addNodeLast($1.node);
      $$.list = argumentExpressionList;
    }
  | argument_expression_list op_comma assignment_expression
    {
      $1.list->addNodeLast($2.node);
      $1.list->addNodeLast($3.node);
      $$.list = $1.list;
    }
  ;

constant
  : INTEGER_CONSTANT
    {
      constant* Constant;
      Constant = new constant;
      Constant->setNodeType(CONSTANT);
      Constant->setDecompositionRule(1);
      integer_constant* integerConstant;
      integerConstant = new integer_constant(strlen(tokval));
      integerConstant->setNodeType(INTEGER_CONST);
      integerConstant->intValue = $1.i;
      strcpy(integerConstant->stringRepresentation, tokval);
      integerConstant->storeIgnored();
      Constant->integerConstant = integerConstant;
      $$.node = Constant;
    }
  | CHARACTER_CONSTANT
    {
      constant* Constant;
      Constant = new constant;
      Constant->setNodeType(CONSTANT);
      Constant->setDecompositionRule(2);
      character_constant* characterConstant;
      characterConstant = new character_constant(strlen($1.s));
      characterConstant->setNodeType(CHARACTER_CONST);
      strcpy(characterConstant->stringRepresentation, $1.s);
      characterConstant->storeIgnored();
      Constant->characterConstant = characterConstant;
      $$.node = Constant;
    }
  | FLOAT_CONSTANT
    {
      constant* Constant;
      Constant = new constant;
      Constant->setNodeType(CONSTANT);
      Constant->setDecompositionRule(3);
      float_constant* floatConstant;
      floatConstant = new float_constant(strlen(tokval));
      floatConstant->setNodeType(FLOAT_CONST);
      floatConstant->floatValue = $1.r;
      strcpy(floatConstant->stringRepresentation, tokval);
      floatConstant->storeIgnored();
      Constant->floatConstant = floatConstant;
      $$.node = Constant;
    }
  | ENUMERATION_CONSTANT
    {
      constant* Constant;
      Constant = new constant;
      Constant->setNodeType(CONSTANT);
      Constant->setDecompositionRule(4);
      enumeration_constant* enumerationConstant;
      enumerationConstant = new enumeration_constant(strlen($1.s));
      enumerationConstant->setNodeType(ENUMERATION_CONST);
      strcpy(enumerationConstant->stringRepresentation, $1.s);
      enumerationConstant->storeIgnored();
      Constant->enumerationConstant = enumerationConstant;
      $$.node = Constant;
    }
  ;

/* -- additional rules to handle preprocessor items -- */

semicolon
  : ';'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter(";");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

open_c_br
  : '{'
    {
      delimiter* Delimiter;                   
      Delimiter = new delimiter("{");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

close_c_br
  : '}'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("}");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_comma
  : ','
    {
      delimiter* Delimiter;
      Delimiter = new delimiter(",");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

equals
  : '='
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("=");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

colon
  : ':'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter(":");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

open_r_br
  : '('
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("(");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

close_r_br
  : ')'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter(")");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

open_s_br
  : '['
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("[");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

close_s_br
  : ']'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("]");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

asterisk
  : '*'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("*");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

dots
  : DDD
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("...");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

ask
  : '?'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("?");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_oror
  : OROR
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("||");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_andand
  : ANDAND
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("&&");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_or
  : '|'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("|");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_xor
  : '^'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("^");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_and
  : '&'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("&");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_equ
  : EQU
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("==");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_nequ
  : NEQ
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("!=");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_less
  : '<'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("<");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_greater
  : '>'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter(">");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_leq
  : LEQ
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("<=");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_geq
  : GEQ
    {
      delimiter* Delimiter;
      Delimiter = new delimiter(">=");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_shl
  : SHL
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("<<");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_shr
  : SHR
    {
      delimiter* Delimiter;
      Delimiter = new delimiter(">>");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_plus
  : '+'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("+");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_minus
  : '-'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("-");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_div
  : '/'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("/");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_mod
  : '%'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("%");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_neg
  : '~'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("~");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_not
  : '!'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("!");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_ptr
  : PTR
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("->");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_addadd
  : ADDADD
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("++");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_subsub
  : SUBSUB
    {
      delimiter* Delimiter;
      Delimiter = new delimiter("--");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

op_dot
  : '.'
    {
      delimiter* Delimiter;
      Delimiter = new delimiter(".");
      Delimiter -> setNodeType(DELIMITER);
      Delimiter -> storeIgnored();
      $$.node = Delimiter;
    }
  ;

keyword_Auto
  : Auto
    {
      keyword* Keyword;
      Keyword = new keyword("auto");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Break
  : Break
    {
      keyword* Keyword;
      Keyword = new keyword("break");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Case
  : Case
    {
      keyword* Keyword;
      Keyword = new keyword("case");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Char
  : Char
    {
      keyword* Keyword;
      Keyword = new keyword("char");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Const
  : Const
    {
      keyword* Keyword;
      Keyword = new keyword("const");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Continue
  : Continue
    {
      keyword* Keyword;
      Keyword = new keyword("continue");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Default
  : Default
    {
      keyword* Keyword;
      Keyword = new keyword("default");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Do
  : Do
    {
      keyword* Keyword;
      Keyword = new keyword("do");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Double
  : Double
    {
      keyword* Keyword;
      Keyword = new keyword("double");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Else
  : Else
    {
      keyword* Keyword;
      Keyword = new keyword("else");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Enum
  : Enum
    {
      keyword* Keyword;
      Keyword = new keyword("enum");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Extern
  : Extern
    {
      keyword* Keyword;
      Keyword = new keyword("extern");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Float
  : Float
    {
      keyword* Keyword;
      Keyword = new keyword("float");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_For
  : For
    {
      keyword* Keyword;
      Keyword = new keyword("for");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Goto
  : Goto
    {
      keyword* Keyword;
      Keyword = new keyword("goto");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_If
  : If
    {
      keyword* Keyword;
      Keyword = new keyword("if");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Int
  : Int
    {
      keyword* Keyword;
      Keyword = new keyword("int");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Long
  : Long
    {
      keyword* Keyword;
      Keyword = new keyword("long");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Register
  : Register
    {
      keyword* Keyword;
      Keyword = new keyword("register");
      Keyword -> setNodeType(KEYWORD);
      $$.node = Keyword;
      Keyword -> storeIgnored();
    }
  ;

keyword_Return
  : Return
    {
      keyword* Keyword;
      Keyword = new keyword("return");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Short
  : Short
    {
      keyword* Keyword;
      Keyword = new keyword("short");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Signed
  : Signed
    {
      keyword* Keyword;
      Keyword = new keyword("signed");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Sizeof
  : Sizeof
    {
      keyword* Keyword;
      Keyword = new keyword("sizeof");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Static
  : Static
    {
      keyword* Keyword;
      Keyword = new keyword("static");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Struct
  : Struct
    {
      keyword* Keyword;
      Keyword = new keyword("struct");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Switch
  : Switch
    {
      keyword* Keyword;
      Keyword = new keyword("switch");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Typedef
  : Typedef
    {
      keyword* Keyword;
      Keyword = new keyword("typedef");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Void
  : Void
    {
      keyword* Keyword;
      Keyword = new keyword("void");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Volatile
  : Volatile
    {
      keyword* Keyword;
      Keyword = new keyword("volatile");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Union
  : Union
    {
      keyword* Keyword;
      Keyword = new keyword("union");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_Unsigned
  : Unsigned
    {
      keyword* Keyword;
      Keyword = new keyword("unsigned");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

keyword_While
  : While
    {
      keyword* Keyword;
      Keyword = new keyword("while");
      Keyword -> setNodeType(KEYWORD);
      Keyword -> storeIgnored();
      $$.node = Keyword;
    }
  ;

%%

extern void yyerror( char *, char * );
